from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
import time
from PIL import Image

def login():
    '''模拟登录并且获得两张验证码'''
    #构造浏览器登录bilibili登录界面
    wb = webdriver.Chrome(r"D:\下载安装包文件\chromedriver.exe")
    wb.maximize_window()
    wb.get("https://passport.bilibili.com/login")
    #设定10秒之内渲染网站完毕
    # wb.implicitly_wait(10)
    wb.implicitly_wait(10)
    # picture = wb.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div')
    # 输入账号密码来获取滑动验证码
    wb.find_element_by_xpath('//input[@id="login-username"]').send_keys('13433627612')
    wb.find_element_by_xpath('//input[@id="login-passwd"]').send_keys('qq88227260')
    wb.find_element_by_xpath('//*[@id="geetest-wrap"]/ul/li[5]/a[1]').click()
    while True:
        # 设定2秒内等滑动验证码渲染
        time.sleep(2)
        #把图片截取下来
        wb.save_screenshot('full_picture.png')
        #把验证码切割
        image = Image.open('full_picture.png')
        code_picture = image.crop((1107,325,1423,517))
        code_picture.save('code.png')
        #获得完整的图片
        full_picture=wb.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]/canvas')
        wb.execute_script("var title = document.querySelector('body > div.geetest_panel.geetest_wind > div.geetest_panel_box.geetest_panelshowslide > div.geetest_panel_next > div > div.geetest_wrap > div.geetest_widget > div > a > div.geetest_canvas_img.geetest_absolute > canvas').style='';", full_picture)
        wb.save_screenshot('full_picture.png')
        image = Image.open('full_picture.png')
        code_picture = image.crop((1107,325,1423,517))
        code_picture.save('code_full.png')
        space = get_space()
        tracks = get_tracks(space)
        button = wb.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div[1]/div[2]/div[2]')
        ActionChains(wb).click_and_hold(button).perform()
        for track in tracks['forward_tracks']:
            ActionChains(wb).move_by_offset(xoffset=track, yoffset=0).perform()
        time.sleep(0.5)
        for back_track in tracks['back_tracks']:
            ActionChains(wb).move_by_offset(xoffset=back_track, yoffset=0).perform()
        ActionChains(wb).move_by_offset(xoffset=-3, yoffset=0).perform()
        ActionChains(wb).move_by_offset(xoffset=3, yoffset=0).perform()
        time.sleep(0.5)
        ActionChains(wb).release().perform()
        try:
            time.sleep(2)
            check=wb.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]').get_attribute('style')
            if check=='display: none;':
                wb.find_element_by_xpath('//*[@id="geetest-wrap"]/ul/li[5]/a[1]').click()
                break
            else:
                wb.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div[2]/div/a[2]').click()
                time.sleep(2)
        except:
            pass
    time.sleep(10)
    wb.close()

def get_space():
    picture1 = Image.open("code_full.png")
    picture2 = Image.open("code.png")
    i = 0
    threshold=60
    left=100
    for i in range(left, picture1.size[0]):
        for j in range(picture1.size[1]):
            rgb1 = picture1.load()[i, j]
            rgb2 = picture2.load()[i, j]
            res1 = abs(rgb1[0] - rgb2[0])
            res2 = abs(rgb1[1] - rgb2[1])
            res3 = abs(rgb1[2] - rgb2[2])
            if not (res1 < threshold and res2 < threshold and res3 < threshold):
                return i +18  # 误差矫正
    # logging.debug('未识别出验证码中的不同位置，或图片定位出现异常')
    return i+18  # 如果没有识别出不同位置，则象征性的滑动，以刷新下一张验证码

def get_tracks(space):
    # 模拟人工滑动，避免被识别为机器
    # space += 10  # 先滑过一点，最后再反着滑动回来
    v = 0
    t = 0.2
    forward_tracks = []
    current = 0
    mid = space * 3 / 5
    while current < space:
        if current < mid:
            a = 2
        else:
            a = -3
        s = v * t + 0.5 * a * (t ** 2)
        v = v + a * t
        current += s
        forward_tracks.append(round(s))
    # 反着滑动到准确位置
    back_tracks = [-2,-2,-2,-2,-3,-3,-2, -5, -5, -4, -5, -10, -3, -4]
    return {'forward_tracks': forward_tracks, 'back_tracks': back_tracks}


if __name__ == "__main__":
    login()






